home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
msysjour
/
vol07
/
03
/
debug
/
badapp.c
< prev
next >
Wrap
Text File
|
1992-05-01
|
13KB
|
430 lines
#include <windows.h>
#include "badapp.h"
#define WINPROC long FAR PASCAL
#define MDIPROC long FAR PASCAL
#define DLGPROC BOOL FAR PASCAL
#define ENUMPROC BOOL FAR PASCAL
#define WINDOWS_PARAMS HWND hWnd, unsigned msg, WORD wParam, LONG lParam
#define DIALOG_PARAMS HWND hDlg, unsigned msg, WORD wParam, LONG lParam
#define ENUM_PARAMS HWND hWnd, LONG lParam
WINPROC WndProc ( WINDOWS_PARAMS );
DLGPROC DlgProc ( WINDOWS_PARAMS );
void AssertTrashedDS ( WORD wAssertValue );
void InitializeDSSafeGuard( void );
/**************************************************************
* *
* Global Variables *
* *
**************************************************************/
#define UNDEF_ASSERT_VAR(p1) int p1;
#define ASSERT_VAR(p1) int p1=42;
// NOTE: Only UNINITIALIZED variables are arranged by the C compiler
// in the order you see them. All pre-initialized variables,
// such as
//
// int PremierSupport = 1;
//
// are moved to a different area of the DS.
//
//
// For these variables, you will want to init them immediately
// using the InitializeDSSafeGaurd() function.
//
UNDEF_ASSERT_VAR(asv1);
HWND ghWnd;
UNDEF_ASSERT_VAR(asv2);
HANDLE ghInst;
UNDEF_ASSERT_VAR(asv3);
char szFullName[20];
UNDEF_ASSERT_VAR(asv4);
ASSERT_VAR(asv5);
char szAppName[] = "BADAPP";
ASSERT_VAR(asv6);
char szCaption[] = "Buggy Windows App";
ASSERT_VAR(asv7);
char szMenuName[] = "PlainMenu";
ASSERT_VAR(asv8);
char szDialogTemplateName[] = "MODALDIALOG";
ASSERT_VAR(asv9);
char szSpace[] = " ";
ASSERT_VAR(asv10);
char szHello[] = "Hello!";
ASSERT_VAR(asv11);
/**************************************************************
* *
* Assertion Tracking Defines *
* *
**************************************************************/
#define WinMain_Entry 1
#define WinMain_Exit 2
#define ModalDialog_Entry 3
#define ModalDialog_Exit 4
#define WndProc_WM_DESTROY 5
#define WndProc_WM_COMMAND_IDM_MODAL_Entry 6
#define WndProc_WM_COMMAND_IDM_MODAL_Exit 7
#define DlgProc_WM_COMMAND_IDOK_Entry 8
#define DlgProc_WM_COMMAND_IDOK_Exit 9
#define DlgProc_WM_COMMAND_IDCANCEL_Entry 10
#define DlgProc_WM_COMMAND_IDCANCEL_Exit 11
/**************************************************************
* *
* WinMain *
* *
**************************************************************/
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow )
{
MSG msg ;
WNDCLASS wndclass ;
InitializeDSSafeGuard();
AssertTrashedDS ( WinMain_Entry );
if (!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNCLIENT;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject ( GRAY_BRUSH ) ;
wndclass.lpszMenuName = (LPSTR)szMenuName ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
return FALSE;
}
ghInst = hInstance;
ghWnd = CreateWindow (szAppName, szCaption,
WS_OVERLAPPEDWINDOW,
100, 100,
200, 200,
NULL, NULL, hInstance, NULL) ;
ShowWindow ( ghWnd, nCmdShow );
UpdateWindow ( ghWnd );
while (GetMessage((LPMSG)&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
AssertTrashedDS ( WinMain_Exit );
return msg.wParam ;
}
/*********************************************************************
* *
* ModalDialog: Calls a Modal Dialog Box *
* *
*********************************************************************/
int ModalDialog ( LPSTR TemplateName, FARPROC FunctionName, LONG dwParam )
{
FARPROC lpDialogProc;
int RetVal;
AssertTrashedDS ( ModalDialog_Entry );
lpDialogProc = MakeProcInstance ( FunctionName, ghInst );
RetVal = DialogBoxParam ( ghInst, TemplateName, ghWnd,
lpDialogProc, (DWORD)dwParam );
FreeProcInstance ( lpDialogProc );
AssertTrashedDS ( ModalDialog_Exit );
return RetVal;
}
/*********************************************************************
* *
* WndProc: Main Message Translator *
* *
*********************************************************************/
WINPROC WndProc ( WINDOWS_PARAMS )
{
switch ( msg )
{
case WM_DESTROY :
AssertTrashedDS ( WndProc_WM_DESTROY );
PostQuitMessage (0) ;
break ;
case WM_COMMAND :
switch ( wParam )
{
case IDM_MODAL :
AssertTrashedDS ( WndProc_WM_COMMAND_IDM_MODAL_Entry );
ModalDialog ( szDialogTemplateName, DlgProc, 0L );
AssertTrashedDS ( WndProc_WM_COMMAND_IDM_MODAL_Exit );
break;
default:
return DefWindowProc ( hWnd, msg, wParam, lParam ) ;
break;
}
break;
default :
return DefWindowProc ( hWnd, msg, wParam, lParam );
}
return 0L ;
}
/********************************************************************
* *
* Vanilla Dialog Box Procedure *
* *
********************************************************************/
// Here is a typical dialog proc. Most of these variables are not used,
// but they are there in order to make the stack frame more resemble
// a typical dialog proc.
DLGPROC DlgProc ( DIALOG_PARAMS )
{
int iPositionOfComma;
char szBuffer[32];
switch (msg)
{
case WM_INITDIALOG:
SetFocus ( GetDlgItem ( hDlg, IDD_NAME ));
return FALSE;
case WM_COMMAND:
switch (wParam)
{
case IDOK:
AssertTrashedDS ( DlgProc_WM_COMMAND_IDOK_Entry );
GetDlgItemText ( hDlg, IDD_NAME, szBuffer, sizeof(szBuffer) );
// Step 1: Find the comma seperating the Last Name and the First Name
// and then zero it out, effectively changing this one
// string into two strings
iPositionOfComma = lstrlen (szBuffer);
while (iPositionOfComma && (szBuffer[iPositionOfComma] != ',')) iPositionOfComma--;
szBuffer[iPositionOfComma] = 0;
// Step 2: Copy the First name into the global buffer
lstrcpy (szFullName, szBuffer+iPositionOfComma+1);
// Step 3: Add a space
lstrcat (szFullName, szSpace );
// Step 4: Add the last name
lstrcat (szFullName, szBuffer );
// Step 5: Say Hi to the user
MessageBox ( hDlg, szFullName, szHello, MB_OK );
AssertTrashedDS ( DlgProc_WM_COMMAND_IDOK_Exit );
break;
case IDCANCEL:
AssertTrashedDS ( DlgProc_WM_COMMAND_IDCANCEL_Entry );
EndDialog ( hDlg, TRUE);
AssertTrashedDS ( DlgProc_WM_COMMAND_IDCANCEL_Exit );
return TRUE;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
/**************************************************************
* *
* WinMain *
* *
**************************************************************/
#define CHECK(p1,p2) \
if (42 != p1) \
{ \
if (!wBadVariable) \
{ \
wBadValue = p1; \
p1 = 42; \
wBadVariable = p2; \
} \
}
void AssertTrashedDS ( WORD wAssertValue )
{
static WORD wQueueValue; // The next open spot in the queue
static WORD wQueue[10]; // The actual queue
WORD wBadVariable;
WORD wBadValue;
//
// These three lines add the passed in AssertionValue into the queue,
// and zero out the next spot (which will be displayed as an asterisk)
//
wQueue[wQueueValue] = wAssertValue;
wQueueValue = (wQueueValue+1)%10;
wQueue[wQueueValue] = 0;
//
// The CHECK macro above will only set the wBadValue and wBadVariable
// values if no asserion violation has occured. Since it is possible
// that multiple assertion variables could have been trashed at the
// same time, we will continue this loop as long as *any* of the
// assertion variables are trashed. Note that the CHECK macro restores
// the trashed assertion varaible once it has detected it. This
// prevents inifinite loops.
//
do
{
// Resetting this varaible makes the assumption that no trashing was done
wBadVariable = 0;
//
// Check all of the variables. Remember that once one trashing has been
// found, the remaining trashed varaibles will remain trashed. The next
// iteration of the do-loop will find the next trashed variable, and
// so on until all trashed variables have been reported.
//
CHECK(asv1,1);
CHECK(asv2,2);
CHECK(asv3,3);
CHECK(asv4,4);
CHECK(asv5,5);
CHECK(asv6,6);
CHECK(asv7,7);
CHECK(asv8,8);
CHECK(asv9,9);
CHECK(asv10,10);
CHECK(asv11,11);
//
// If we actually found a trashing, report it
//
if (wBadVariable)
{
int i;
char szMsg[255];
char szMsg1[255];
char szMsg2[128];
char szNum[10];
//
// Generate a string of the queue values, using a "*" for the zero
// value to indicate the end of the queue
//
*szMsg1 = 0;
for ( i = 0; i < 10; i++ )
{
if (wQueue[i])
wsprintf ( szNum, "%d", wQueue[i]);
else
lstrcpy ( szNum, "*" );
if (i != 9)
lstrcat ( szNum, "," );
lstrcat ( szMsg1, szNum );
}
//
// Create a cute string showing the programmer/unlucky enduser the list
//
wsprintf ( szMsg, "%s (%s)",
(LPSTR)"Assertion Failure",
(LPSTR)szMsg1
);
//
// Create a caption saying which varaible was trashed, and it's value
//
wsprintf ( szMsg2, "Assertion Variable asv%d=%d", wBadVariable, wBadValue );
//
// Alert the programmer/unlucky enduser
//
MessageBox ( NULL, szMsg, szMsg2, MB_SYSTEMMODAL );
} // end if bad value
}
while (wBadVariable); // Keep doing this until assertion varaibles are clean
} // end function
/*********************************************************************
* *
* *
* *
*********************************************************************/
void InitializeDSSafeGuard( void )
{
asv1 = 42;
asv2 = 42;
asv3 = 42;
asv4 = 42;
}